package org.travelfusion.xmlclient.ri.handler.plane;

import static org.travelfusion.xmlclient.util.TfXAPIUtil.parseDate;

import java.util.HashMap;
import java.util.Map;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

import org.travelfusion.xmlclient.ri.xobject.plane.XFlightSegment;

class FlightSegmentSubHandler {

  private final CheckRoutingHandler parent;

  private final Map<String, String> operatorNames = new HashMap<String, String>();

  FlightSegmentSubHandler(CheckRoutingHandler parent) {
    this.parent = parent;
  }

  Map<String, String> getOperatorNames() {
    return operatorNames;
  }

  private static enum State {
    ROOT, //
    ORIGIN, //
    DESTINATION, //
    OPERATOR, //
    FLIGHT_CODE, //
    TRAVEL_CLASS
  }

  public XFlightSegment handleResponse() throws Exception {
    XFlightSegment segment = new XFlightSegment();

    StringBuilder builder = new StringBuilder();
    String currentName = null;
    boolean build = false;

    String operatorName = null;

    final XMLStreamReader responseReader = parent.getResponseReader();

    State state = State.ROOT;
    done: for (int event; ((event = responseReader.next()) != XMLStreamConstants.END_DOCUMENT);) {
      switch (event) {
        case XMLStreamConstants.START_ELEMENT:
          currentName = responseReader.getName().getLocalPart();
          builder.setLength(0);
          switch (state) {
            case ROOT:
              if ("Origin".equals(currentName)) {
                state = State.ORIGIN;
                build = true;
              }
              else if ("Destination".equals(currentName)) {
                state = State.DESTINATION;
                build = true;
              }
              else if ("DepartDate".equals(currentName)) {
                build = true;
              }
              else if ("ArriveDate".equals(currentName)) {
                build = true;
              }
              else if ("Duration".equals(currentName)) {
                build = true;
              }
              else if ("Operator".equals(currentName)) {
                operatorName = null;
                state = State.OPERATOR;
                build = true;
              }
              else if ("FlightId".equals(currentName)) {
                state = State.FLIGHT_CODE;
                build = true;
              }
              else if ("TravelClass".equals(currentName)) {
                state = State.TRAVEL_CLASS;
                build = true;
              }
              break;
          }
          break;
        case XMLStreamConstants.CHARACTERS:
          if (build) {
            builder.append(responseReader.getTextCharacters(), responseReader.getTextStart(), responseReader.getTextLength());
          }
          break;
        case XMLStreamConstants.END_ELEMENT:
          currentName = responseReader.getName().getLocalPart();
          switch (state) {
            case ROOT:
              if ("DepartDate".equals(currentName)) {
                segment.setDepartureTime(parseDate(builder.toString(), parent.getTZDeltaMinutes()));
                build = false;
              }
              else if ("ArriveDate".equals(currentName)) {
                segment.setArrivalTime(parseDate(builder.toString(), parent.getTZDeltaMinutes()));
                build = false;
              }
              else if ("Duration".equals(currentName)) {
                segment.setDuration(Integer.parseInt(builder.toString()));
                build = false;
              }
              else if ("Segment".equals(currentName)) {
                break done;
              }
              break;
            case ORIGIN:
              if ("Code".equals(currentName)) {
                segment.setOrigin(builder.toString());
                build = false;
              }
              else if ("Origin".equals(currentName)) {
                state = State.ROOT;
                build = false;
              }
              break;
            case DESTINATION:
              if ("Code".equals(currentName)) {
                segment.setDestination(builder.toString());
                build = false;
              }
              else if ("Destination".equals(currentName)) {
                state = State.ROOT;
                build = false;
              }
              break;
            case OPERATOR:
              if ("Code".equals(currentName)) {
                segment.setOperator(builder.toString().trim());
                if (segment.getOperator().length() == 0) {
                  segment.setOperator(null);
                }
              }
              else if ("Name".equals(currentName)) {
                operatorName = builder.toString().trim();
              }
              else if ("Operator".equals(currentName)) {
                if (segment.getOperator() != null && operatorName.length() > 0) {
                  operatorNames.put(segment.getOperator(), operatorName);
                }
                state = State.ROOT;
                build = false;
              }
              break;
            case FLIGHT_CODE:
              if ("Code".equals(currentName)) {
                segment.setCode(builder.toString());
                build = false;
              }
              else if ("FlightId".equals(currentName)) {
                state = State.ROOT;
                build = false;
              }
              break;
            case TRAVEL_CLASS:
              if ("TfClass".equals(currentName)) {
                segment.setTravelClass(builder.toString());
                build = false;
              }
              else if ("TravelClass".equals(currentName)) {
                state = State.ROOT;
                build = false;
              }
              break;
          }
          break;
      }
    }

    return segment;
  }
}
